package com.lyn.pluginhost

import android.annotation.SuppressLint
import android.app.Application
import android.app.Service
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import com.google.gson.reflect.TypeToken
import com.lyn.pluginapi.entity.PluginData
import com.lyn.pluginapi.entity.PluginInfo
import com.lyn.pluginapi.entity.WrapPluginInfo
import com.lyn.pluginapi.gson.MY_GSON
import com.lyn.pluginhost.activity.ProxyPluginActivityStack
import com.lyn.pluginhost.service.PluginHostService
import com.lyn.pluginhost.utils.ProcessUtil
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlin.coroutines.resume

/**
 * 插件host 管理
 * @author longyn 2025/07/10
 * @version 1.0.0
 */
class PluginHostManager : ServiceConnection {

    companion object {
        const val TAG = "PluginHostManager"
        val instance by lazy { PluginHostManager() }
    }

    private lateinit var application: Application
    private var pluginAidlInterface: PluginAidlInterface? = null
    private val handler: Handler = Handler(Looper.getMainLooper())
    var initializeListener:((Boolean)->Unit?)?=null

    /**
     * 初始化
     * @param application app 上下文
     * @param initializeListener 初始化监听
     */
    fun initialize(application: Application,initializeListener:((Boolean)->Unit)) {
        if (!ProcessUtil.isMainProcess(application)){
            return
        }
        this@PluginHostManager.initializeListener = initializeListener
        if (this@PluginHostManager::application.isInitialized) {
            return
        }
        this.application = application
        reBindService()
    }

    private fun reBindService(){
        val intent = Intent(application, PluginHostService::class.java)
        this.application.bindService(intent, this, Service.BIND_AUTO_CREATE)
    }

    override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
        Log.d(TAG,"onServiceConnected")
        service?.let {
            pluginAidlInterface = PluginAidlInterface.Stub.asInterface(it)
            pluginAidlInterface?.initialize(object : ResultCallbackAidlInterface.Stub() {
                override fun onSuccess(args: String?) {
                    Log.d(TAG,"pluginAidlInterface initialize onSuccess args:${args}")
                    this@PluginHostManager.initializeListener?.invoke(true)
                }

                override fun onFail(code: Int, msg: String?) {
                    Log.d(TAG,"pluginAidlInterface initialize onFail code:${code} msg:${msg}")
                    this@PluginHostManager.initializeListener?.invoke(false)
                }
            })
            return
        }
        this@PluginHostManager.initializeListener?.invoke(false)
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        pluginAidlInterface = null
        Log.d(TAG,"onServiceDisconnected")
        this@PluginHostManager.initializeListener?.invoke(false)
        handler.postDelayed({
            reBindService()
        },5000)
    }


    /**
     * 加载插件
     * @param path 插件路径
     */
    suspend fun loadPlugin(path: String) {
        withTimeoutOrNull(6000) {
            suspendCancellableCoroutine { block ->
                pluginAidlInterface?.loadPlugin(path, object : ResultCallbackAidlInterface.Stub() {
                    override fun onSuccess(args: String?) {
                        handler.post {
                            block.resume(true)
                        }
                    }

                    override fun onFail(code: Int, msg: String?) {
                        handler.post {
                            block.resume(false)
                        }
                    }
                })
            }

        }

    }

    /**
     * 加载全部插件
     * @return 插件信息list
     */
    suspend fun loadAllPlugin(): MutableList<WrapPluginInfo> {
        ProxyPluginActivityStack.instance.closeAll()
        val pluginInfos = withTimeoutOrNull(6000) {
            suspendCancellableCoroutine<MutableList<PluginInfo>> { block ->
                pluginAidlInterface?.loadAllPlugin(object : ResultCallbackAidlInterface.Stub() {
                    override fun onSuccess(args: String?) {
                        Log.d(TAG, "loadAllPlugin 全部插件:${args}")
                        val pluginData = MY_GSON.fromJson(args, PluginData::class.java)
                        val pluginInfos = pluginData.pluginInfos ?: mutableListOf()
                        handler.post {
                            block.resume(pluginInfos)
                        }
                    }

                    override fun onFail(code: Int, msg: String?) {
                        handler.post {
                            Log.d(TAG, "loadAllPlugin onFail:${msg}")
                            block.resume(mutableListOf())
                        }
                    }
                })
            }
        } ?: mutableListOf()
        val wrapPluginInfos = mutableListOf<WrapPluginInfo>()
        for (pluginInfo in pluginInfos){
            val pluginLogo = getPluginLogo(pluginInfo.id, pluginInfo.path)
            val wrapPluginInfo = WrapPluginInfo(pluginInfo, pluginLogo)
            wrapPluginInfos.add(wrapPluginInfo)
        }
        return wrapPluginInfos
    }

    /**
     * 获取全部插件
     * @return 插件信息list
     */
    suspend fun getAllPlugin(): MutableList<WrapPluginInfo> {
        val pluginInfos = withTimeoutOrNull(6000) {
            suspendCancellableCoroutine<MutableList<PluginInfo>> { block ->
                pluginAidlInterface?.getAllPlugin(object : ResultCallbackAidlInterface.Stub() {
                    override fun onSuccess(args: String?) {
                        val type = object : TypeToken<PluginInfo>() {}.type
                        val pluginInfos =
                            MY_GSON.fromJson<MutableList<PluginInfo>>(args ?: "", type)
                        handler.post {
                            block.resume(pluginInfos)
                        }
                    }

                    override fun onFail(code: Int, msg: String?) {
                        handler.post {
                            block.resume(mutableListOf())
                        }
                    }
                })
            }
        } ?: mutableListOf()
        val wrapPluginInfos = mutableListOf<WrapPluginInfo>()
        for (pluginInfo in pluginInfos){
            val pluginLogo = getPluginLogo(pluginInfo.id, pluginInfo.path)
            val wrapPluginInfo = WrapPluginInfo(pluginInfo, pluginLogo)
            wrapPluginInfos.add(wrapPluginInfo)
        }
        return wrapPluginInfos
    }

    /**
     * 获取插件logo
     * @param pluginId 插件id
     * @param path 插件路径
     * @return bitmap logo
     */
    suspend fun getPluginLogo(pluginId: String, path: String): Bitmap {
        try {
            val bytes = withTimeoutOrNull(6000) {
                suspendCancellableCoroutine<ByteArray> { block ->
                    pluginAidlInterface?.getPluginLogo(pluginId, path, object :
                        GetLogoResultCallbackAidlInterface.Stub() {
                        override fun onSuccess(data: ByteArray?) {
                            block.resume(data ?: byteArrayOf())
                        }

                        override fun onFail(code: Int, msg: String?) {
                            block.resume(byteArrayOf())
                        }
                    })
                }
            } ?: byteArrayOf()
            if (bytes.isEmpty()) {
                @SuppressLint("UseCompatLoadingForDrawables")
                val drawable = application.resources.getDrawable(
                    R.drawable.plugin_default_icon,
                    application.theme
                )
                val bitmap = Bitmap.createBitmap(
                    drawable.intrinsicWidth,
                    drawable.intrinsicHeight,
                    Bitmap.Config.ARGB_8888
                )
                val canvas = Canvas(bitmap)
                canvas.drawColor(Color.TRANSPARENT)
                drawable.setBounds(0, 0, canvas.width, canvas.height)
                drawable.draw(canvas)
                return bitmap
            }
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        @SuppressLint("UseCompatLoadingForDrawables")
        val drawable = application.resources.getDrawable(R.drawable.plugin_default_icon,application.theme)
        val bitmap = Bitmap.createBitmap(
            drawable.intrinsicWidth,
            drawable.intrinsicHeight,
            Bitmap.Config.ARGB_8888
        )
        val canvas = Canvas(bitmap)
        canvas.drawColor(Color.TRANSPARENT)
        drawable.setBounds(0, 0, canvas.width, canvas.height)
        drawable.draw(canvas)
        return bitmap
    }

    /**
     * 删除插件
     * @param id 插件id
     * @return true 成功 false 失败
     */
    suspend fun removePlugin(id: String): Boolean {
        return withTimeoutOrNull(6000) {
            suspendCancellableCoroutine<Boolean> { block ->
                pluginAidlInterface?.removePlugin(id, object : ResultCallbackAidlInterface.Stub() {
                    override fun onSuccess(args: String?) {
                        handler.post {
                            block.resume(true)
                        }
                    }

                    override fun onFail(code: Int, msg: String?) {
                        handler.post {
                            block.resume(false)
                        }
                    }
                })
            }
        } ?: false
    }

    /**
     * 打开插件
     * @param id 插件id
     * @param resultCallback 结果回调
     */
    fun openPlugin(id: String, resultCallback: (Boolean) -> Unit) {
        pluginAidlInterface?.openPlugin(id, object : ResultCallbackAidlInterface.Stub() {
            override fun onSuccess(args: String?) {
                handler.post {
                    resultCallback.invoke(true)
                }
            }

            override fun onFail(code: Int, msg: String?) {
                handler.post {
                    resultCallback.invoke(false)
                }
            }
        })
    }

    /**
     * 关闭插件
     * @param id 插件id
     * @param resultCallback 结果回调
     */
    fun closePlugin(id: String, resultCallback: (Boolean) -> Unit) {
        pluginAidlInterface?.closePlugin(id, object : ResultCallbackAidlInterface.Stub() {
            override fun onSuccess(args: String?) {
                handler.post {
                    resultCallback.invoke(true)
                }
            }

            override fun onFail(code: Int, msg: String?) {
                handler.post {
                    resultCallback.invoke(false)
                }
            }
        })
    }
}